package jmine.tec.utils.io;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Converte um InputStream em um arquivo temporario que eh apagado quando chega no final do stream ou quando o metodo {@link #close()} eh
 * chamado
 * 
 * @author takeshi
 */
public class TemporaryFileInputStream extends InputStream {

    private final File fileToUse;

    private final FileInputStream fin;

    /**
     * C'tor
     * 
     * @param source o InputStream source
     * @throws IOException e
     */
    public TemporaryFileInputStream(InputStream source) throws IOException {
        this.fileToUse = File.createTempFile("tmp", "bin");
        FileOutputStream fout = new FileOutputStream(this.fileToUse);
        IOUtils.copyFullyClose(source, fout);
        fout.close();
        this.fin = new FileInputStream(this.fileToUse);
    }

    /**
     * C'tor
     * 
     * @param file o arquivo a ser lido
     * @throws IOException e
     */
    public TemporaryFileInputStream(File file) throws IOException {
        this.fileToUse = file;
        this.fin = new FileInputStream(this.fileToUse);
    }

    /**
     * {@inheritDoc}
     * 
     * @see java.io.InputStream#read(byte[])
     */
    @Override
    public int read(byte[] b) throws IOException {
        int read = this.fin.read(b);
        if (read < 0) {
            this.close();
        }
        return read;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        int read = this.fin.read(b, off, len);
        if (read < 0) {
            this.close();
        }
        return read;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int read() throws IOException {
        int r = this.fin.read();
        if (r < 0) {
            this.close();
        }
        return r;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void close() throws IOException {
        this.fin.close();
        if (this.fileToUse.exists()) {
            if (!this.fileToUse.delete()) {
                this.fileToUse.deleteOnExit();
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int available() throws IOException {
        return this.fin.available();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean markSupported() {
        return this.fin.markSupported();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized void mark(int readlimit) {
        this.fin.mark(readlimit);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public synchronized void reset() throws IOException {
        this.fin.reset();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public long skip(long n) throws IOException {
        return this.fin.skip(n);
    }

}
